﻿using System;
using System.Linq;
using System.Text;
using viBook.Common;
using viBook.Models;

namespace viBook.Repositories
{
    public class ActivityRepository : IActivityRepository
    {
        private readonly viBookContext _context = new viBookContext();

        #region IActivityRepository Members

        public IQueryable<Activity> All
        {
            get { return _context.Activities; }
        }

        public Activity Find(int id)
        {
            return _context.Activities.Find(id);
        }

        public IQueryable<Activity> FindByUser(int userId)
        {
            return _context.Activities.Where(a => a.UserId == userId).OrderByDescending(a => a.CreatedDate);
        }

        public void Insert(Activity activity)
        {
            _context.Activities.Add(activity);
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public void CreateActivity(object model, string type)
        {
            var description = String.Empty;
            var userId = 0;
            var createdDate = new DateTime();
            var referId = 0;
            if (model == null)
            {
                return;
            }
            switch (type)
            {
                case Constant.RegisteredType:
                    {
                        var user = (User) model;
                        userId = user.Id;
                        createdDate = user.JoinedDate;
                        description = Constant.RegisteredActivity;
                        break;
                    }
                case Constant.CreatedBookType:
                    {
                        var book = (Book) model;
                        userId = book.UploadedBy;
                        createdDate = book.UploadedDate;
                        referId = book.Id;


                        var builder = new StringBuilder(Constant.BookDetailsPath);
                        builder.Append(book.Id);
                        description = String.Format(Constant.CreatedBookActivity, builder, book.Title);

                        break;
                    }
                case Constant.CommentedBookType:
                    {
                        var bookComment = (BookComment) model;
                        userId = bookComment.UserId;
                        createdDate = bookComment.CreatedDate;
                        referId = bookComment.Id;

                        var builder = new StringBuilder(Constant.BookDetailsPath);
                        builder.Append(bookComment.BookId);
                        var shortContent = new StringBuilder();
                        if (bookComment.Content.Length > Constant.MaximumShortCommentCharacters)
                        {
                            shortContent.Append(bookComment.Content.Substring(0, Constant.MaximumShortCommentCharacters));
                            shortContent.Append("...");
                        }
                        else
                        {
                            shortContent.Append(bookComment.Content);
                        }

                        description = string.Format(Constant.CommentedBookActivity, shortContent, builder,
                                                    bookComment.Book.Title);
                        break;
                    }
                case Constant.CommentedChapterType:
                    {
                        var chapterComment = (ChapterComment) model;
                        userId = chapterComment.UserId;
                        createdDate = chapterComment.CreatedDate;
                        referId = chapterComment.Id;

                        var chapterUrl = new StringBuilder(Constant.ChapterDetailsPath);
                        var bookUrl = new StringBuilder(Constant.BookDetailsPath);
                        var shortContent = new StringBuilder();
                        chapterUrl.Append(chapterComment.ChapterId);
                        var chapter = _context.Chapters.Find(chapterComment.ChapterId);
                        bookUrl.Append(chapter.BookId);
                        if (chapterComment.Content.Length > Constant.MaximumShortCommentCharacters)
                        {
                            shortContent.Append(chapterComment.Content.Substring(0,  Constant.MaximumShortCommentCharacters));
                            shortContent.Append("...");
                        }
                        else
                        {
                            shortContent.Append(chapterComment.Content);
                        }

                        description = string.Format(Constant.CommentedChapterActivity, shortContent, chapterUrl,
                                                    chapter.ChapterName, bookUrl,
                                                    chapter.Book.Title);

                        break;
                    }
                case Constant.LikedBookType:
                    {
                        var bookLike = (BookLike) model;
                        userId = bookLike.UserId;
                        createdDate = bookLike.CreatedDate;
                        referId = bookLike.Id;

                        var bookUrl = new StringBuilder(Constant.BookDetailsPath);
                        bookUrl.Append(bookLike.BookId);

                        description = string.Format(Constant.LikedBookActivity, bookUrl, bookLike.Book.Title);
                        break;
                    }
                case Constant.LikedChapterType:
                    {
                        var chapterLike = (ChapterLike) model;
                        userId = chapterLike.UserId;
                        createdDate = chapterLike.CreatedDate;
                        referId = chapterLike.Id;

                        var bookUrl = new StringBuilder(Constant.BookDetailsPath);
                        var chapterUrl = new StringBuilder(Constant.ChapterDetailsPath);
                        bookUrl.Append(chapterLike.Chapter.BookId);
                        chapterUrl.Append(chapterLike.ChapterId);

                        description = string.Format(Constant.LikedChapterActivity, chapterUrl,
                                                    chapterLike.Chapter.ChapterName, bookUrl,
                                                    chapterLike.Chapter.Book.Title);
                        break;
                    }
                case Constant.LikedBookCommentType:
                    {
                        var bookCommentLike = (BookCommentLike) model;
                        userId = bookCommentLike.UserId;
                        createdDate = bookCommentLike.CreatedDate;
                        referId = bookCommentLike.Id;

                        var bookUrl = new StringBuilder(Constant.BookDetailsPath);
                        var userUrl = new StringBuilder(Constant.UserAccountPath);
                        bookUrl.Append(bookCommentLike.Comment.BookId);
                        userUrl.Append(bookCommentLike.Comment.UserId);

                        description = string.Format(Constant.LikedBookCommentActivity, userUrl,
                                                    bookCommentLike.Comment.User.DisplayName, bookUrl,
                                                    bookCommentLike.Comment.Book.Title);
                        break;
                    }
                case Constant.LikedChapterCommentType:
                    {
                        var chapterCommentLike = (ChapterCommentLike) model;
                        userId = chapterCommentLike.UserId;
                        createdDate = chapterCommentLike.CreatedDate;
                        referId = chapterCommentLike.Id;

                        var bookUrl = new StringBuilder(Constant.BookDetailsPath);
                        var userUrl = new StringBuilder(Constant.UserAccountPath);
                        var chapterUrl = new StringBuilder(Constant.ChapterDetailsPath);
                        bookUrl.Append(chapterCommentLike.Comment.Chapter.BookId);
                        userUrl.Append(chapterCommentLike.Comment.UserId);
                        chapterUrl.Append(chapterCommentLike.Comment.ChapterId);

                        description = string.Format(Constant.LikedChapterCommentActivity, userUrl,
                                                    chapterCommentLike.Comment.User.DisplayName, chapterUrl,
                                                    chapterCommentLike.Comment.Chapter.ChapterName, bookUrl,
                                                    chapterCommentLike.Comment.Chapter.Book.Title);
                        break;
                    }
            }
            if (userId != 0)
            {
                var activity = new Activity
                                   {
                                       UserId = userId,
                                       Description = description,
                                       CreatedDate = createdDate,
                                       Type = type,
                                       ReferId = referId
                                   };

                _context.Activities.Add(activity);
            }
        }

        public void DeleteActivity(int referId, string type)
        {
            IQueryable<Activity> query = _context.Activities.Where(a => a.ReferId == referId && a.Type.Equals(type));
            if (query.Count() > 0)
            {
                _context.Activities.Remove(query.First());
            }
        }

        public BookLike FindBookLike(int bookId, int userId)
        {
            IQueryable<BookLike> query = _context.BookLikes.Where(b => b.BookId == bookId && b.UserId == userId);
            if (query.Count() > 0)
            {
                return query.First();
            }
            return null;
        }

        public ChapterLike FindChapterLike(int chapterId, int userId)
        {
            IQueryable<ChapterLike> query =
                _context.ChapterLikes.Where(b => b.ChapterId == chapterId && b.UserId == userId);
            if (query.Count() > 0)
            {
                return query.First();
            }
            return null;
        }

        public BookCommentLike FindBookCommentLike(int commentId, int userId)
        {
            IQueryable<BookCommentLike> query =
                _context.BookCommentLikes.Where(b => b.CommentId == commentId && b.UserId == userId);
            if (query.Count() > 0)
            {
                return query.First();
            }
            return null;
        }

        public ChapterCommentLike FindChapterCommentLike(int commentId, int userId)
        {
            IQueryable<ChapterCommentLike> query =
                _context.ChapterCommentLikes.Where(c => c.CommentId == commentId && c.UserId == userId);
            if (query.Count() > 0)
            {
                return query.First();
            }
            return null;
        }

        #endregion
    }

    public interface IActivityRepository
    {
        IQueryable<Activity> All { get; }
        Activity Find(int id);
        IQueryable<Activity> FindByUser(int userId);
        void Insert(Activity activity);
        void Save();
        void CreateActivity(object model, string type);
        void DeleteActivity(int referId, string type);
        BookLike FindBookLike(int bookId, int userId);
        ChapterLike FindChapterLike(int chapterId, int userId);
        BookCommentLike FindBookCommentLike(int commentId, int userId);
        ChapterCommentLike FindChapterCommentLike(int commentId, int userId);
    }
}